/*
 * @Author: Jahaw 
 * @Date: 2024-08-13 17:32:46 
 * @Last Modified by: Jahaw
 * @Last Modified time: 2024-08-14 09:41:53
 */
import { execSync } from 'child_process';
import md5 from 'js-md5';
import type { VersionJSON, VersionType } from './type';

/**
 * generate json file content for version
 * @param {string} version - git commit hash or packaging time
 * @returns A string
 */
export function generateJSONFileContent(version: string, silence = false) {
  const content: VersionJSON = {
    version,
  }
  if (silence)
    content.silence = true

  return JSON.stringify(content, null, 2)
}

export function generateJsFileContent(fileSource: string, version: string, options: Options) {
  const { logVersion = true } = options
  let content = `${fileSource}
  window.__checkUpdateSetup__(${JSON.stringify(options)});`
  if (logVersion) {
    const fn = typeof logVersion === 'function' ? logVersion : logVersionDefault
    content += `
      ;const logFn = ${fn.toString()}
      ;logFn('${version}', ${Date.now()})
    `
  }
  return content
}

export const injectVersionTpl = (version: string) => {
  return `window.pluginWebUpdateNotice_version = '${version}';`
}

export function logVersionDefault(version: string, releaseTime: number) {
  // eslint-disable-next-line no-console
  console.log(`version: %c${version}`, 'color: #1677ff')

  // eslint-disable-next-line no-console
  console.log(`release time: %c${new Date(releaseTime).toLocaleString()}`, 'color: #1677ff')
}

/**
 * The function returns the first 8 characters of the MD5 hash of a given string.
 * @param {string} fileString - a string that represents the content of a file.
 * @returns the first 8 characters of the MD5 hash of the file
 */
export function getFileHash(fileString: string) {
  return md5(fileString).slice(0, 8)
}

/**
 * It returns the current timestamp
 * @returns The current time in milliseconds.
 */
export function getTimestamp() {
  return `${Date.now()}`
}

/**
 * It returns the version of the host project's package.json file
 * @returns The version of the package.json file in the root of the project.
 */
export function getHostProjectPkgVersion() {
  try {
    return process.env.npm_package_version as string
  }
  catch (err) {
    console.warn(`
    ======================================================
    [web-update-notice] cannot get the version of the host project's package.json file!
    ======================================================`)
    throw err
  }
}

/**
 * If the current directory is a git repository, return the current commit hash
 * @returns The git commit hash of the current branch.
 */
export function getGitCommitHash() {
  try {
    return execSync('git rev-parse --short HEAD').toString().replace('\n', '').trim()
  }
  catch (err) {
    console.warn(`
    ======================================================
    [web-update-notice] Not a git repository!
    ======================================================`)
    throw err
  }
}

export function getCustomVersion(version?: string) {
  if (!version) {
    console.warn(`
    ======================================================
    [web-update-notice] The versionType is 'custom', but the customVersion is not specified!
    ======================================================`)
    throw new Error('The versionType is \'custom\', but the customVersion is not specified!')
  }
  return version
}

export function getVersion(versionType?: VersionType, customVersion?: string) {
  const getVersionStrategies: Record<VersionType, () => string> = {
    pkg_version: getHostProjectPkgVersion,
    git_commit_hash: getGitCommitHash,
    build_timestamp: getTimestamp,
    custom: () => getCustomVersion(customVersion)
  }

  const defaultStrategyMap = {
    Git: 'git_commit_hash'
  }

  const versionType_ = versionType || defaultStrategyMap['Git'] as VersionType

  try {
    const strategy = getVersionStrategies[versionType_]
    if (!strategy) {
      console.warn(`
      ======================================================
      [web-update-notice] The version type '${versionType}' is not supported!, we will use the packaging timestamp instead.
      ======================================================`)
      return getTimestamp()
    }

    return strategy()
  }
  catch (err) {
    console.warn(`
    ======================================================
    [web-update-notice] get version throw a error, we will use the packaging timestamp instead.
    ======================================================`)
    console.error(err)
    return getTimestamp()
  }
}